import UAParser from "ua-parser-js";
import storage from './storage';
import {onFCP, onTTFB, onLCP, onFID} from 'web-vitals';

/** 捕获模块 */

//执行级错误捕捉
function capture_execution_error() {
    window.onerror = function (message, source, lineno, colno, error) {
        console.log('[logjs] trigger >>> onerror');
        let error_info = {
            timeStep: new Date().getTime(),
            type: message,
            source: source,
            lineno: lineno,
            colno: colno,
            error: error,
            logType: "error",
            errorMessage: message,
            href: window.location.href,
        };
        storage.save("error_info", error_info);
    };
}

//终端信息捕捉
function capture_terminal_info() {

    getIP();
    getTTFB();
    getFCP();
    getLCP();
    getFID();

    let ua = navigator.userAgent || '';
    let parser = new UAParser(ua);
    let ua_info = parser.getResult();

    let terminal_info = {
        resolving_power: screen.width + "*" + screen.height,
        referrer: getReferrer(),
        ...ua_info
    };
    storage.save("terminal_info", terminal_info);
}

function getReferrer(){
    let ref = '';
    if (document.referrer.length > 0) {
        ref = document.referrer;
    }else{
        ref = window.location.href;
    }
    return ref;
}

//获取ip等相关信息
function getIP() {
    let ipElement = document.createElement("script");
    ipElement.src = location.protocol + "//pv.sohu.com/cityjson?ie=utf-8";

    ipElement.onload = function (e) {
        let obj = {
            ip: returnCitySN.cip,
            city: returnCitySN.cname
        };
        storage.save("terminal_info", obj);
        document.head.removeChild(ipElement);
    };

    document.head.appendChild(ipElement);
}

function capture_click_info() {
    let body = document.body;
    if (!body) return void 0;
    body.onclick = function (e) {
        let eleLocation = [];
        e?.path?.map( item => {
            if(!!item.localName){
                eleLocation.push(`${item.localName}${item.className ? '.' + item.className : ''}`);
            }
        });
        let click_info = {
            logType: "click",
            eleType: e.target.localName,
            eleContent: e.target.innerText,
            timeStep: new Date().getTime(),
            href: window.location.href,
            eleLocation: eleLocation.join('<=')
        };
        storage.save("click_info", click_info);
    };
}

//自定义行为捕捉
function diy_log(obj, tag){

    let diy_info = {
        logType: "diy",
        obj: obj || void 0,
        tag: tag,
        timeStep: new Date().getTime()
    };

    storage.save("diy_info", diy_info);
}

//获取整体资源信息推进IOlist，同时计算当前终端的性能信息(如果无performance对象，则停止计算页面性能以及获取IO信息)
function get_performance_resource(params){
    if(!(window.performance || window.msPerformance || window.webkitPerformance)) return console.warn('[log.js] Failed to get page performance information successfully.');

    //计算性能信息
    if(!performance.timing) return console.warn('[log.js] Failed to get performance information successfully.');

    let timing = performance.timing;
    let tempPerformance = {
        fp: 'Failed to get',//白屏耗时-单位毫秒
        redirect_time: 'Failed to get',//重定向耗时-单位毫秒
        domain_lookup_time: 'Failed to get',//DNS查询耗时-单位毫秒
        connect_time: 'Failed to get',//TCP链接耗时-单位毫秒
        response_time: 'Failed to get',//HTTP请求耗时-单位毫秒
        dom_complete_time: 'Failed to get',//DOM解析耗时-单位毫秒
    };

    tempPerformance.fp = timing.responseStart - timing.navigationStart;
    tempPerformance.redirect_time = timing.redirectEnd - timing.redirectStart;
    tempPerformance.domain_lookup_time = timing.domainLookupEnd - timing.domainLookupStart;
    tempPerformance.response_time = timing.responseEnd - timing.responseStart;
    tempPerformance.dom_complete_time = timing.domComplete - timing.domInteractive;
    tempPerformance.connect_time = timing.connectEnd - timing.connectStart;

    storage.save('performance_info', tempPerformance);
}

function getTTFB(){
    //第一字节时间 (TTFB) 是在实验室和现场测量连接建立时间和 Web 服务器响应能力的一个基础指标。它有助于识别 Web 服务器何时对请求的响应速度太慢。对 HTML 文档的请求，该指标先于其他所有的加载性能指标。
    //应用应将该值努力控制在 0.8s 以内
    onTTFB((metric) => {
        console.log('ttfb',metric);
        storage.save('performance_info', { ttfb: metric.value ?? 'Failed to get' });
    })
}

function getFCP(){
    //首次内容绘制 (FCP) 是测量感知加载速度的一个以用户为中心的重要指标，因为该项指标会在用户首次在屏幕上看到任何内容时，在页面加载时间轴中标记出相应的点，迅捷的 FCP 有助于让用户确信某些事情正在进行。
    //应用应将该值努力控制在 1.8s 以内
    onFCP((metric => {
        console.log('fcp',metric);
        storage.save('performance_info', { fcp: metric.value ?? 'Failed to get' });
    }))
}

function getLCP(){
    //最大内容绘制 (LCP) 是测量感知加载速度的一个以用户为中心的重要指标，因为该项指标会在页面的主要内容基本加载完成时，在页面加载时间轴中标记出相应的点，迅捷的 LCP 有助于让用户确信页面是有效的。
    //应用应将该值努力控制在 2.5s 以内
    onLCP((metric => {
        console.log('lcp',metric);
        storage.save('performance_info', { lcp: metric.value ?? 'Failed to get' });
    }))
}

function getFID(){
    //首次输入延迟 (FID) 是测量加载响应度的一个以用户为中心的重要指标，因为该项指标将用户尝试与无响应页面进行交互时的体验进行了量化，低 FID 有助于让用户确信页面是有效的。
    //应用应将该值努力控制在 100毫秒 以内
    onFID((metric => {
        console.log('fid',metric);
        storage.save('performance_info', { fid: metric.value ?? 'Failed to get' });
    }))
}

function window_onload(params){

    window.onload = function (){
        console.log('[logjs] trigger >>> onload');
        get_performance_resource(params);
        capture_click_info(params);
    }

}

//启动所有捕捉
function capture_start_all(params) {
    for (let key in capture) {
        if (key === "start_all" || key === 'diy_log' || key === 'get_performance_resource') {
            continue;
        }
        capture[key](params);
    }
}

//创建io信息监控
function create_io_monitor(params){
    const observer = new PerformanceObserver( list => {

        let ioFilter = storage.config_info.ioFilter;
        let resourcesList = list.getEntries();
        resourcesList = resourcesList.filter( item => ioFilter(item) && item.name !== storage.config_info.sendAddress && item.name !== `${location.protocol}//pv.sohu.com/cityjson?ie=utf-8`);

        let tempList = [];
        resourcesList.map( item => {
            let tempItem = item.toJSON();
            tempItem.logType = 'io';
            tempItem.timeStep = new Date().getTime();
            tempList.push(tempItem);
        })

        tempList.map( item => {
            storage.save('io_info', item);
        })

    })
    observer.observe({entryTypes:['longtask', 'frame', 'navigation', 'resource', 'mark', 'measure']});
}


let capture = {
    execution_error: capture_execution_error, //执行错误
    terminal_info: capture_terminal_info, //终端信息获取
    click_info: capture_click_info, //点击信息获取
    window_onload: window_onload,//页面加载完成
    diy_log: diy_log,//自定义日志
    get_performance_resource: get_performance_resource,//获取资源加载情况
    create_io_monitor: create_io_monitor,//创建io信息监控
    start_all: capture_start_all, //启动所有监控
};


export default capture;
